package com.nowcoder.community.config;

import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.CommunityUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Configuration
public class Securityconfig extends WebSecurityConfigurerAdapter implements CommunityConstant {

    // 忽略的资源
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 忽略 /resources/**
        web.ignoring().antMatchers("/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 授权 [authorizeRequests:授权请求]
        http.authorizeRequests()
                // 拦截请求路径(需要登录才能访问的)
                .antMatchers(
                        "/user/setting",
                        "/user/upload",
                        "/discuss/add",
                        // "/comment/add/**" -> **指代id
                        "/comment/add/**",
                        "/letter/**",
                        "/notice/**",
                        "/like",
                        "/follow",
                        "/unfollow"
                )
                // 授权
                // 所有用户都可访问
                .hasAnyAuthority(
                        AUTHORITY_USER,
                        AUTHORITY_ADMIN,
                        AUTHORITY_MODERATOR
                )
                .antMatchers(
                        "/discuss/top",
                        "/discuss/wonderful"
                )
                // 版主可访问
                .hasAnyAuthority(
                        AUTHORITY_MODERATOR
                )
                // 管理员可访问
                .antMatchers(
                        "/discuss/delete",
                        "/actuator/**",
                        "data/**"
                )
                .hasAnyAuthority(
                        AUTHORITY_ADMIN
                )
                // 其他请求都可以访问
                .anyRequest().permitAll()
                // 禁用防csrf攻击
                .and().csrf().disable();

        // 权限问题的处理
        http.exceptionHandling()

                // 没有登录时的处理
                .authenticationEntryPoint(new AuthenticationEntryPoint() {
                    @Override
                    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                        String xRequestWith = request.getHeader("x-requested-with");

                        // 如果是异步请求，返回json由前端处理
                        if ("XMLHttpRequest".equals(xRequestWith)){
                            // 设置响应格式
                            // application/plain : 普通文本格式
                            response.setContentType("application/plain;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            // 响应一个流
                            writer.write(CommunityUtil.getJSONString(403,"你还没有登录哦"));
                        }
                        // 如果是同步请求，跳转到登录页面
                        else{
                            response.sendRedirect(request.getContextPath() + "/login");
                        }
                    }
                })
                // 权限不足时的处理
                .accessDeniedHandler(new AccessDeniedHandler() {
                    @Override
                    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                        String xRequestWith = request.getHeader("x-requested-with");

                        // 如果是异步请求，返回json由前端处理
                        if ("XMLHttpRequest".equals(xRequestWith)){
                            // 设置响应格式
                            // application/plain : 普通文本格式
                            response.setContentType("application/plain;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            // 响应一个流
                            writer.write(CommunityUtil.getJSONString(403,"你没有访问此功能的权限"));
                        }
                        // 如果是同步请求，跳转到登录页面
                        else{
                            response.sendRedirect(request.getContextPath() + "/denied");
                        }
                    }
                });

        // security底层会拦截 /logout 的请求，进行处理
        // 覆盖它的拦截请求执行自己的退出代码
        http.logout().logoutUrl("/securityLogout");
    }
}
